package top.metaspace.io.bio;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author panjun
 * @date 2018/6/26. bio实现的socket通信demo
 */
public class BioDemoServer {

	public static void main(String[] args) throws Exception {
		BioDemoServer server = new BioDemoServer();
		server.server3();
	}

	/**
	 * 这种方式是一次性的
	 */
	public void server1() throws Exception {
		/**
		 * 第一步绑定端口
		 */
		ServerSocket serverSocket = new ServerSocket(10000);
		/**
		 * 阻塞在accept方法上
		 */
		Socket socket = serverSocket.accept();
		/**
		 * 获取输入流
		 */
		InputStream inputStream = socket.getInputStream();
		/**
		 * 从输入流获取数据
		 */
		InputStreamReader reader = new InputStreamReader(inputStream);
		BufferedReader bf = new BufferedReader(reader);
		String info;
		while ((info = bf.readLine()) != null) {
			System.out.println(info);
		}
		/**
		 * 关闭输入流
		 */
		socket.shutdownInput();
		/**
		 * 响应客户端
		 */
		OutputStream os = socket.getOutputStream();
		PrintWriter writer = new PrintWriter(os);
		writer.print("hello");
		writer.flush();
		/**
		 * 关闭资源
		 */
		writer.close();
		os.close();
		bf.close();
		reader.close();
		inputStream.close();
		socket.close();
		serverSocket.close();
	}

	/**
	 * 我们知道第一中方式是一次性的 那么为了能够处理多个请求，我们可以这么做 但是这种方式一次同时只能处理一个请求
	 */
	public void server2() throws Exception {
		/**
		 * 第一步绑定端口
		 */
		ServerSocket serverSocket = new ServerSocket(10000);
		while (true) {
			/**
			 * 阻塞在accept方法上
			 */
			Socket socket = serverSocket.accept();
			/**
			 * 获取输入流
			 */
			InputStream inputStream = socket.getInputStream();
			/**
			 * 从输入流获取数据
			 */
			InputStreamReader reader = new InputStreamReader(inputStream);
			BufferedReader bf = new BufferedReader(reader);
			String info;
			while ((info = bf.readLine()) != null) {
				System.out.println(info);
			}
			/**
			 * 关闭输入流
			 */
			socket.shutdownInput();
			/**
			 * 响应客户端
			 */
			OutputStream os = socket.getOutputStream();
			PrintWriter writer = new PrintWriter(os);
			writer.print("hello");
			writer.flush();
			/**
			 * 关闭资源
			 */
			writer.close();
			os.close();
			bf.close();
			reader.close();
			inputStream.close();
			socket.close();
		}


	}

	/**
	 * 为了一次能处理多个请求，我们很自然的就想到用多线程
	 * 这种形式称为伪异步io，比较适用于大量客户端和服务器进行少量数据交互的场景
	 * 但是由于写操作也是阻塞的那么当需要服务器响应大量数据，或者网络比较慢的时候
	 * 写操作一直不完成，造成线程池线程暴涨，直至必须进入任务队列等待，继续暴涨，任务有可能被拒绝
	 */
	public void server3() throws Exception {
		ThreadPoolExecutor tp = new ThreadPoolExecutor(100, 100, 0, TimeUnit.MILLISECONDS,
				new LinkedBlockingQueue<>(100));
		ServerSocket serverSocket = new ServerSocket(10000);
		while (true) {
			/**
			 * 阻塞在accept方法上
			 */
			final Socket socket = serverSocket.accept();
			tp.execute(new Runnable() {
				@Override
				public void run() {
					try {
						/**
						 * 获取输入流
						 */
						InputStream inputStream = socket.getInputStream();
						/**
						 * 从输入流获取数据
						 */
						InputStreamReader reader = new InputStreamReader(inputStream);
						BufferedReader bf = new BufferedReader(reader);
						String info;
						while ((info = bf.readLine()) != null) {
							System.out.println(info);
						}
						/**
						 * 关闭输入流
						 */
						socket.shutdownInput();
						/**
						 * 响应客户端
						 */
						OutputStream os = socket.getOutputStream();
						PrintWriter writer = new PrintWriter(os);
						writer.print("hello");
						writer.flush();
						/**
						 * 关闭资源
						 */
						writer.close();
						os.close();
						bf.close();
						reader.close();
						inputStream.close();
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}

				}
			});
		}



	}

}
